#
# Copyright (c) 2002-2007 Eric Wallengren
# This file is part of the Continuous Automated Build and Integration
# Environment (CABIE)
#
# CABIE is distributed under the terms of the GNU General Public
# License version 2 or any later version.  See the file COPYING for copying
# permission or http://www.gnu.org.
#
# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR
# IMPLIED, without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  ANY USE IS AT YOUR OWN RISK.
#
# Permission to modify the code and to distribute modified code is granted,
# provided the above notices are retained, and a notice that the code was
# modified is included with the above copyright notice.
#

package cmdset;

use Carp;

#
# Command set for CABIE.
#
my %cmdset = (

    #
    # Admin commands are only seen by those whose machines are defined
    # by the use of the 'authorize' function or if no machines exist in
    # the auth table.
    #
    admincmds => {
    
        adduser => {
            type     => I,
            function => "adduser",
            help     => 'Usage:
    	adduser -p port -u username -f first -l last [-m mail ] [-g group]
    	Add new user to CM server',
        },
    
        authorize => {
            type     => I,
            function => "authorize",
            help     => 'Usage:
    	authorize -c computername
    	authorize computername to control builds',
        },
    
        authorized => {
            type     => I,
            function => "whosauthorized",
            help     => 'Usage:
    	authorized
    	display list of computers authorized to control builds',
        },
    
        build => {
            type     => E,
            function => "%s/bin/builder.pl",
            help     => 'Usage:
    	build -n jobname [-j jobno]',
        },
    
        cleanjob => {
            type     => I,
            function => "cleanjob",
            help     => 'Usage:
    	cleanjob -n jobname -j jobno <-f -r -t testname>
    	Remove all records associated with <jobname> <jobno>.
    	-f forces removal
    	-r rolls back to previous build
    	-t testname remove test semaphores only for <testname>
    	This is permanent - it cannot not be un-done!',
        },
    
        clone => {
            type     => I,
            function => "clone",
            help     => 'Usage:
    	clone -n oldjobname -c newjobname
    	Create new job by copying oldjob configuration',
        },
    
        connectlog => {
            type     => I,
            function => "connect_log",
            help     => 'Usage:
	connectlog [-l limit]
	display client connection log [limit to limit number of records]',
        },
    
        createjob => {
            type     => I,
            function => "createjob",
            help     => 'Usage:
    	createjob -n jobname 
    	          -p (p4 port/cvs root/svn repository)
    	          -c (p4 client/cvs module/svn directory)
    	          -r sourceroot
    	          -t debug|retail|both
    	          -d toolsdir
    	          -k keeplevel
    	          -s sccs
    	          -b browserlink
    	          -m global failure notification
    	          -C "comment"
    	          [-D] dump existing job in cmd line format',
        },
    
        deluser => {
            type     => I,
            function => "deluser",
            help     => 'Usage:
    	deluser -p port -u username [-f first -l last -g group]
    	Remove user from CM server',
        },
    
        disable => {
            type     => I,
            function => "lock_build",
            help     => 'Usage:
    	disable -n job
    	Disable build job',
        },
    
        dumpconfig => {
            type     => I,
            function => "dumpconfig",
            help     => 'Usage:
    	dumpconfig
    	Display buildserver configuration loaded from buildconf.pm',
        },
    
        enable => {
            type     => I,
            function => "unlock_build",
            help     => 'Usage:
    	enable -n job [-f -k]
    	Enable build job 
    	[-f force semaphore removal]
    	[-k kill running build process] (requires -f)',
        },
    
        free => {
            type     => I,
            function => "free",
            help     => 'Usage:
    	free -n jobname -j jobno
    	Release locks allowing jobno for build jobname to be deleted
    	by the buildserver',
        },
    
        getid => {
            type     => I,
            function => "getid",
            help     => 'Usage:
    	getid
    	Display buildserver process ID',
        },
    
        keep => {
            type     => I,
            function => "keep",
            help     => 'Usage:
    	keep -n jobname -j jobno [-c comment]
    	Keep jobname for build jobno from being automatically deleted',
        },
    
        kill => {
            type     => I,
            function => "do_kill",
            help     => 'Usage:
    	kill -p pid -s signal
    	kill process by PID (see ps) on the server',
        },
    
        nextjob => {
            type     => I,
            function => "get_syncs",
            help     => 'Usage:
    	nextjob -n jobname
    	display updates CM system will make for jobname with next sync',
        },
    
        notify => {
            type     => I,
            function => "notify",
            help     => 'Usage:
    	notify -n jobname -f firstjob -l lastjob -c comment
    	Send email with comment to all submitters of jobname
    	from firstjob to lastjob',
        },
    
        promote => {
            type     => I,
            function => "promote",
            help     => 'Usage:
    	promote -c comment -n jobname -j jobno [-t type -f from]
    	Promote jobname jobno for formal testing or release',
        },
    
        recover => {
            type     => I,
            function => "recover",
            help     => 'Usage:
    	recover -n jobname
    	Recover active jobs accidently removed by enable command',
        },
    
        rejectlog => {
            type     => I,
            function => "reject_log",
            help     => 'Usage:
	rejectlog [-l limit]
	display client rejection log [limit to limit number of records]',
        },
    
        removejob => {
            type     => I,
            function => "deljob",
            help     => 'Usage:
    	removejob -n jobname [-f]
    	Remove defined job from the buildserver [-f permanent deletion]',
        },
    
        restorejob => {
            type     => I,
            function => "addjob",
            help     => 'Usage:
    	restorejob -n jobname
    	Add previously defined job back to the buildserver',
        },
    
        set => {
            type     => I,
            function => "do_set",
            help     => 'Usage:
	set
	Display build server environment variables',
        },
    
        shutdown => {
            type     => I,
            function => "shutdown",
            help     => ' Usage:
    	shutdown
    	shutdown buildserver processes',
        },
    
        testserver => {
            type     => I,
            function => "testserver",
            help     => 'Usage:
    	testserver -l || <-f server> 
    	View status of servers running tests (-l)
    	Free (-f servername) server for testing',
        },
    
        treeperms => {
            type     => I,
            function => "treeperms",
            help     => 'Usage:
    	treeperms -n job -m module -u userid -a|-r|-l (add, remove or list)
    	Authorize/unauthorize checkins to a module
    	To view available groups use -n jobname -m all -l
    	To view users in a module use -n jobname -m module -l',
        },
    
        unauthorize => {
            type     => I,
            function => "unauthorize",
            help     => 'Usage:
    	unauthorize -c machinename
    	remove computername from authorization list',
        },
    
    },

    #
    # Shared commands are seen by anyone using the command line interface 
    # into CABIE.
    #
    sharedcmds => {
    
        buildlog => {
            type     => I,
            function => "getbuild_log",
            help     => 'Usage:
    	buildlog -n jobname -t retail|debug [-w]
    	retrieve buildlog of defined job',
        },
    
        changed => {
            type     => I,
            function => "changed",
            help     => 'Usage:
    	changed -n jobname -j jobno [-e endjobno]
    	Display list of files updated for job jobno',
        },
    
        commands => {
            type     => I,
            function => "display_commands",
            help     => 'Usage:
    	commands -l -w 
    	Display supported command set',
        },
    
        debuglog => {
            type     => I,
            function => "debuglog",
            help     => 'Usage:
    	debuglog -n jobname
    	complete debug log of defined job',
        },
    
        describe => {
            type     => I,
            function => "describe_job",
            help     => 'Usage:
    	describe -n job
    	describe charastics of defined job',
        },
    
        elapsed => {
            type     => I,
            function => "elapsed",
            help     => 'Usage:
    	elapsed -n job
    	Display elapsed time for current build job',
        },
    
        errorlog => {
            type     => I,
            function => "geterror_log",
            help     => 'Usage:
    	errorlog -n jobname -t retail|debug 
    	retrieve errorlog of defined job',
        },
    
        genweb => {
            type     => I,
            function => "genweb",
            help     => 'Usage:
    	genweb -n joblist -l limit
    	Generate web view of buildserver status for jobs in joblist 
    	Display up to last limit jobs',
        },
    
        help => {
            type     => I,
            function => "display_command_usage",
            help     => 'Usage:
    	help [command]
    	Display [command] usage',
        },
    
        incomplete => {
            type     => I,
            function => "get_fails",
            help     => 'Usage:
    	incomplete -n jobname [-l limit] 
    	Will display (optionally limit) build numbers of failed builds 
    	for jobname',
        },
    
        instructions => {
            type     => I,
            function => "instructions",
            help     => 'Usage:
    	instructions -n jobname
    	instructions for building a defined job locally',
        },
    
        joblog => {
            type     => I,
            function => "do_joblog",
            help     => 'Usage:
    	joblog -n jobname
    	complete run log of defined job',
        },
    
        jobstate => {
            type     => I,
            function => "jobstate",
            help     => 'Usage:
    	jobstate
    	Display buildserver job status',
        },
    
        lastchange => {
            type     => I,
            function => "get_changes",
            help     => 'Usage:
    	lastchange -n jobname [-l n]
    	display last [n] updates for jobname.',
        },
    
        laststart => {
            type     => I,
            function => "get_starts",
            help     => 'Usage:
    	laststart [-l n]
    	display last [n] buildserver starts', 
        },
    
        ps => {
            type     => I,
            function => "do_ps",
            help     => 'Usage:
    	ps [-t]
    	Build Unix style process table on the server',
        },
    
        removed => {
            type     => I,
            function => "show_removed",
            help     => 'Usage:
    	removed
    	display jobs no longer under build server control',
        },
    
        runstats => {
            type     => I,
            function => "runstats",
            help     => 'Usage:
    	runstats -n job
    	Display statistics for [optionally -l] last build jobs
    
    	-a displays only the average build time
    	-r displays raw time in ticks (seconds) useful
    	for feeding into a script',
        },
    
        servers => {
            type     => I,
            function => "servers",
            help     => 'Usage:
    	servers
    	display other build servers',
        },
    
        status => {
            type     => I,
            function => "build_status",
            help     => 'Usage:
    	status -n job 
    	Check build status',
        },
    
        subscribe => {
            type     => I,
            function => "subscribe",
            help     => 'Usage:
    	subscribe -n jobname -e emailaddress
    	subscribe for automatic email notification of defined job',
        },
    
        subscribers => {
            type     => I,
            function => "subscribers",
            help     => 'Usage:
    	subscribers -n jobname
    	display email subscription list for a defined job',
        },
    
        synclog => {
            type     => I,
            function => "getsync_log",
            help     => 'Usage:
    	synclog -n jobname
    	retrieve synclog of defined job',
        },
    
        sysinfo => {
            type     => I,
            function => "sysinfo",
            help     => 'Usage:
    	sysinfo
    	display hardware/software configuration for build server',
        },
    
        teststatus => {
            type     => I,
            function => "teststatus",
            help     => 'Usage:
    	teststatus -n (jobname|all)
    	          [-j jobno]
    	          [-l n limit to n records]
    	          [-r include running tests]
    	          [-p include pending tests]
    	          [-c include completed tests]',
        },
    
        unsubscribe => {
            type     => I,
            function => "unsubscribe",
            help     => 'Usage:
    	unsubscribe -n jobname -e emailaddress
    	unsubscribe from automatic email notification of defined job',
        },
    
        whatsnew => {
            type     => I,
            function => "whatsnew",
            help     => 'Usage:
    	whatsnew
    	display latest changes made to the build server',
        },
    
        xmldump => {
            type     => I,
            function => "xmldump",
            help     => 'Usage:
    	xmldump -n (jobname|all)
    	       [-j jobno]
    	       [-s (server|all)]
    	       [-l limit]
    	       [-f include files]
    	       [-c include comments]
    	       [-t include test status]
    	       [-r include running jobs]
    	       [-p include promotion info]',
        },
    
    },

    #
    # These are functions available to everyone using the CLI on the monitor
    # port of CABIE.
    #
    smsharedcmds => {
    
        commands => {
            type     => I,
            function => "display_commands",
            help     => 'Usage:
    	commands -l -w 
    	Display supported command set',
        },
    
        help => {
            type     => I,
            function => "display_command_usage",
            help     => 'Usage:
    	help [command]
    	Display [command] usage',
        },
    
        nextjob => {
            type     => I,
            function => "get_syncs",
            help     => 'Usage:
    	nextjob -n jobname
    	display updates CM system will make for jobname with next sync',
        },
    
        passed => {
            type     => I,
            function => "passed",
            help     => 'Usage:
    	passed -n jobname -j jobno
    	marks build as good and keeps it until freed by request',
        },
    
        run => {
            type     => E,
            function => "external",
            help     => 'Usage:
	run [command name] 
	execute external command on the build server',
        },
    
    },

    #
    # These are functions available to those whose machines are found in the
    # authtable or if no machines are defined in the auth table.  Thsese 
    # commands are only visible on the monitor port.
    #
    smadmincmds => {

        pendingtest => {
            type     => I,
            function => "pendingtest",
            help     => 'Usage:
	pendingtest -n [testname]
	display imaging machines for [testname]',
        },

    },
    
    #
    # These are user specific commands that replace a few admin commands
    # of the same name.
    #
    usercmds => {
    
        connectlog => {
            type     => I,
            function => "my_connect_log",
            help     => 'Usage:
	connectlog [-l limit]
	display client connection log [limit to limit number of records]',
        },
    
        rejectlog => {
            type     => I,
            function => "my_reject_log",
            help     => 'Usage:
	rejectlog [-l limit]
	display client rejection log [limit to limit number of records]',
        },

    },

    #
    # Even though commands are defined above, we still need signatures to 
    # pass into the rpc object.  The signature is the contents of each 
    # hash, with the hashname and name being the same.  The signature will
    # always remain the same and code will be supplied at the time of 
    # loading each procedure into the rpc object.
    #
    signatures => {
    
        adduser => {
            name      => "adduser",
            signature => ['array string'],
            code      => '',
        },
    
        authorize => {
            name      => "authorize",
            signature => ['array string'],
            code      => '',
        },
    
        authorized => {
            name      => "authorized",
            signature => ['array string'],
            code      => '',
        },
    
        build => {
            name      => "build",
            signature => ['array string'],
            code      => '',
        },
    
        buildlog => {
            name      => "buildlog",
            signature => ['array string'],
            code      => '',
        },
    
        changed => {
            name      => "changed",
            signature => ['array string'],
            code      => '',
        },
    
        cleanjob => {
            name      => "cleanjob",
            signature => ['array string'],
            code      => '',
        },
    
        clone => {
            name      => "clone",
            signature => ['array string'],
            code      => '',
        },
    
        commands => {
            name      => "commands",
            signature => ['array string'],
            code      => '',
        },
    
        connectlog => {
            name      => "connectlog",
            signature => ['array string'],
            code      => '',
        },
    
        createjob => {
            name      => "createjob",
            signature => ['array string'],
            code      => '',
        },
    
        debuglog => {
            name      => "debuglog",
            signature => ['array string'],
            code      => '',
        },
    
        deluser => {
            name      => "deluser",
            signature => ['array string'],
            code      => '',
        },
    
        describe => {
            name      => "describe",
            signature => ['array string'],
            code      => '',
        },
    
        disable => {
            name      => "disable",
            signature => ['array string'],
            code      => '',
        },
    
        dumpconfig => {
            name      => "dumpconfig",
            signature => ['array string'],
            code      => '',
        },
    
        elapsed => {
            name      => "elapsed",
            signature => ['array string'],
            code      => '',
        },
    
        enable => {
            name      => "enable",
            signature => ['array string'],
            code      => '',
        },
    
        errorlog => {
            name      => "errorlog",
            signature => ['array string'],
            code      => '',
        },
    
        free => {
            name      => "free",
            signature => ['array string'],
            code      => '',
        },
    
        genweb => {
            name      => "genweb",
            signature => ['array string'],
            code      => '',
        },
    
        getid => {
            name      => "getid",
            signature => ['array string'],
            code      => '',
        },
    
        helo => {
            name      => "helo",
            signature => ['array string'],
            code      => '',
        },
    
        help => {
            name      => "help",
            signature => ['array string'],
            code      => '',
        },
    
        incomplete => {
            name      => "incomplete",
            signature => ['array string'],
            code      => '',
        },
    
        instructions => {
            name      => "instructions",
            signature => ['array string'],
            code      => '',
        },
    
        joblog => {
            name      => "joblog",
            signature => ['array string'],
            code      => '',
        },
    
        jobstate => {
            name      => "jobstate",
            signature => ['array string'],
            code      => '',
        },
    
        keep => {
            name      => "keep",
            signature => ['array string'],
            code      => '',
        },
    
        kill => {
            name      => "kill",
            signature => ['array string'],
            code      => '',
        },
    
        lastchange => {
            name      => "lastchange",
            signature => ['array string'],
            code      => '',
        },
    
        laststart => {
            name      => "laststart",
            signature => ['array string'],
            code      => '',
        },
    
        nextjob => {
            name      => "nextjob",
            signature => ['array string'],
            code      => '',
        },
    
        notify => {
            name      => "notify",
            signature => ['array string'],
            code      => '',
        },
    
        passed => {
            name      => "passed",
            signature => ['array string'],
            code      => '',
        },
    
        promote => {
            name      => "promote",
            signature => ['array string'],
            code      => '',
        },
    
        ps => {
            name      => "ps",
            signature => ['array string'],
            code      => '',
        },
    
        recover => {
            name      => "recover",
            signature => ['array string'],
            code      => '',
        },
    
        rejectlog => {
            name      => "rejectlog",
            signature => ['array string'],
            code      => '',
        },
    
        removed => {
            name      => "removed",
            signature => ['array string'],
            code      => '',
        },
    
        removejob => {
            name      => "removejob",
            signature => ['array string'],
            code      => '',
        },
    
        restorejob => {
            name      => "restorejob",
            signature => ['array string'],
            code      => '',
        },
    
        run => {
            name      => "run",
            signature => ['array string'],
            code      => '',
        },
    
        runstats => {
            name      => "runstats",
            signature => ['array string'],
            code      => '',
        },
    
        servers => {
            name      => "servers",
            signature => ['array string'],
            code      => '',
        },
    
        set => {
            name      => "set",
            signature => ['array string'],
            code      => '',
        },
    
        shutdown => {
            name      => "shutdown",
            signature => ['array string'],
            code      => '',
        },
    
        status => {
            name      => "status",
            signature => ['array string'],
            code      => '',
        },
    
        subscribe => {
            name      => "subscribe",
            signature => ['array string'],
            code      => '',
        },
    
        subscribers => {
            name      => "subscribers",
            signature => ['array string'],
            code      => '',
        },
    
        synclog => {
            name      => "synclog",
            signature => ['array string'],
            code      => '',
        },
    
        sysinfo => {
            name      => "sysinfo",
            signature => ['array string'],
            code      => '',
        },
    
        testserver => {
            name      => "testserver",
            signature => ['array string'],
            code      => '',
        },
    
        teststatus => {
            name      => "teststatus",
            signature => ['array string'],
            code      => '',
        },
    
        treeperms => {
            name      => "treeperms",
            signature => ['array string'],
            code      => '',
        },
    
        unauthorize => {
            name      => "unauthorize",
            signature => ['array string'],
            code      => '',
        },
    
        unsubscribe => {
            name      => "unsubscribe",
            signature => ['array string'],
            code      => '',
        },
    
        whatsnew => {
            name      => "whatsnew",
            signature => ['array string'],
            code      => '',
        },
    
        xmldump => {
            name      => "xmldump",
            signature => ['array string'],
            code      => '',
        },
    
    },

);

#
# Do not edit anything below this line...
#
# Object constructor...
#
sub new {

    my $that = shift;
    my $class = ref($that) || $that;
    my $self = {
        %cmdset,
    };
    bless $self, $class;
    return $self;
}

#
# Autoload definitions in this package...
#
sub AUTOLOAD {

    my $self = shift;
    my $type = ref($self) || croak "$self is not an object";
    my $name = $AUTOLOAD;
    $name =~ s/.*://;
    unless (exists $self->{$name}) {
        croak "Can't access `$name` field in an object of class $type";
    }
    if (@_) {
        return $self->{$name} = shift;
    } else {
        return $self->{$name};
    }
}

1;
